/**
 * @class Edk.Event
 * Event类，就是一个提供事件服务的类，写得简简单单，不求多元、繁复（明显没有比Ext都考虑得多，那是一种方向）。
 * 好像但凡研究JS到一定阶段的人，都要搞清楚事件吧，嗯～必修课。
 * 事件的立论基础大家可以从观察者模式得到许多灵感，当然就是必须有第三方的“中立”观察者，
 * 一边提供订阅事件的接口，一边让组件触发事件的fireEvent()。
 * 前言：

不得不承认，有时候从新写一个库是一件很辛苦的事情。但是，相比较之下，直接使用别人写好的软件来修改，难道这样痛苦的程度就会减少吗？
 
基于事件模式的设计
JS的一大好处就是对Function天然的良性支持。这一点纵观眼下多少语言都未必能够赋予这种地位，有的即使赋予了，但率直来讲，也没有JS的那样的流通性的地位。试问一下，现今有多少主流语言是对Function这一类型主打的？若没有JS带来的影响，可能这一观念认识知道的人，不计发烧玩家、专家级人马，少之又少，或是又是其他具有“忽悠”价值的概念来代替这一朴质的概念……

事件本身与Function形影不离。好多GUI系统都以Function为编程的中心，因为制定GUI的过程往往就是制定Function的过程。事件类型一旦明确用哪一个好之后，开发人员所关心的便是这个事件到底应该执行些什么过程。若过程可以以一个变量或对象来表示，再给他起个名字，我们从某个角度上理解，也可以说该过程被抽象化了。抽象有什么好处？就是把一些必要的过程先写好，以后在复用。直截了当的说，我定义函数为一变量，可以全局变量，也可以私有变量，看您怎么用它——还可以当作参数传来传去。

也是一下子这样说有点跨越性太大，不易接受。如果是真的，操作起来究竟有什么好处呢？首先我们得从了解函数其意义的本质上去入手理解。什么？函数是什么？？这不是初中层次的内容？……哎呀，插一句，不是怕大家见笑哦，我就是看了什么好东西，一味东拿来一点西拿来一点拼装一起，还自诩高级，其实没有扎实的基础知识联系，准吃亏！哎～回头来还比不过老老实实的说明一下基础内容。——各位已深明大义的看官请掠过。
 */
$$.event = function(){
	this.events = {};
	this.addEvents = function(){
		var eventName;
		for(var i = 0; i < arguments.length; i++){
			eventName = String(arguments[i]).toLowerCase();
			this.events[eventName] = [];
		}
	}
	
	/**
	  *
	  * @param {String} name
	  * @param {Array}  args
	  * @return {Boolean}
	  */
	this.fireEvent = function(name) {
		var listeners = this.events[name.toLowerCase()];
		if (listeners && listeners.length) {
			var 
			 arg1 = arguments[1]
			,arg2 = arguments[2]
			,arg3 = arguments[3]
			,arg4 = arguments[4];
			
			for (var i = 0, ln = listeners.length; i < ln; i++) {
				if((listeners[i])(arg1, arg2, arg3, arg4) === false){
					return false;
				}
			}
		}
		return true;
	}
	
	/**
	  *
	  * @param {String}   name
	  * @param {Function} fn
	  * @return {this}
	  */
	this.addListener = function(name, fn, scope) {
		var eventObj = this.events[String(name).toLowerCase()];
		if(!eventObj){
			throw '没有该事件！请使用addEvent()增加事件';
		}
		if(scope){
			fn = fn.createDelegate(scope);
		}
		eventObj.push(fn);
		return this;
	}
	
	this.on = this.addListener;
	
	/**
	  *
	  * @param {String}   name
	  * @param {Function} fn
	  * @return {this}
	  */
	this.removeListener = function(name, fn) {
		if (this.events[name]) {
			Array.remove(this.events[name], fn);
		}
		return this;
	}
}

/**
 * @class $$.Observable
 * 简单的事件类。
 */
$$.Observable = function(ObservableList){
	if(ObservableList){
		this.addObservable(ObservableList);
	}
}
$$.Observable.prototype = {
	toString: function(){
		return 'Observable';
	}
	,addObservable : function(){
		// 创建事件结构
		this.Observables = this.Observables || {};
		for(var i = 0 ;i < arguments.length; i++){
			this.Observables[String(arguments[i]).toLowerCase()] = [];
		}		
	}
	,addListener: function(ObservableName, ObservableHandler, scope, option){
		var thatObservable = this.Observables[ObservableName.toLowerCase()];
		if(!thatObservable){
			throw "No such Observable";
		}if(!ObservableHandler){
			throw 'No passing Function!';
		}else{
			// ObservableObj
			thatObservable.push({
				 fn		: ObservableHandler
				,scope  : scope || $$.emptyObj
				,cfg 	: option
			});		
		}
	}
	,hasObservable  : function(ObservableName){
		return !!(this.Observables[ObservableName.toLowerCase()]);
	}
	,fireObservable : function(ObservableName){
		var thatObservable = this.Observables[ObservableName.toLowerCase()]
			
		if(!thatObservable){
			throw "No such Observable";
		}else{
			var ObservableObj, args = Array.prototype.slice.call(arguments, 1);
			for(var i = 0 ;i < thatObservable.length; i++){
				ObservableObj = thatObservable[i];
				ObservableObj.fn.apply(ObservableObj.scope, args);
			}
			return true;
		}
	}
};
// shorthands
$$.Observable.prototype.on = $$.Observable.prototype.addListener;